"""
相似度匹配模块 - 提供文本相似度计算和案例匹配功能
"""
import math
from typing import List, Tuple, Dict
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import jieba

class SimilarityMatcher:
    """相似度匹配器类"""
    
    def __init__(self):
        """初始化相似度匹配器"""
        self.vectorizer = TfidfVectorizer(
            tokenizer=self._jieba_tokenizer,
            lowercase=False,
            token_pattern=None
        )
    
    def _jieba_tokenizer(self, text):
        """使用jieba进行中文分词"""
        return jieba.lcut(text)
    
    def calculate_cosine_similarity(self, text1: str, text2: str) -> float:
        """
        计算两个文本的余弦相似度
        
        Args:
            text1: 第一个文本
            text2: 第二个文本
            
        Returns:
            余弦相似度值 (0-1)
        """
        if not text1 or not text2:
            return 0.0
        
        # 向量化文本
        try:
            vectors = self.vectorizer.fit_transform([text1, text2])
            # 计算余弦相似度
            similarity = cosine_similarity(vectors[0], vectors[1])[0][0]
            return float(similarity)
        except:
            return 0.0
    
    def calculate_jaccard_similarity(self, text1: str, text2: str) -> float:
        """
        计算两个文本的Jaccard相似度
        
        Args:
            text1: 第一个文本
            text2: 第二个文本
            
        Returns:
            Jaccard相似度值 (0-1)
        """
        if not text1 or not text2:
            return 0.0
        
        # 分词
        words1 = set(jieba.lcut(text1))
        words2 = set(jieba.lcut(text2))
        
        # 计算交集和并集
        intersection = words1.intersection(words2)
        union = words1.union(words2)
        
        if not union:
            return 0.0
        
        # 计算Jaccard相似度
        jaccard = len(intersection) / len(union)
        return jaccard
    
    def find_similar_cases(self, query: str, cases: List[Dict], top_k: int = 5) -> List[Tuple[Dict, float]]:
        """
        在案例库中查找相似案例
        
        Args:
            query: 查询文本
            cases: 案例列表，每个案例包含title和description字段
            top_k: 返回最相似的K个案例
            
        Returns:
            相似案例列表，每个元素为(案例, 相似度)的元组
        """
        if not query or not cases:
            return []
        
        # 计算每个案例的相似度
        similarities = []
        for case in cases:
            # 组合案例的标题和描述
            case_text = f"{case.get('title', '')} {case.get('description', '')}"
            
            # 计算相似度（可以使用不同的相似度计算方法）
            cosine_sim = self.calculate_cosine_similarity(query, case_text)
            jaccard_sim = self.calculate_jaccard_similarity(query, case_text)
            
            # 综合相似度（可以调整权重）
            combined_similarity = 0.7 * cosine_sim + 0.3 * jaccard_sim
            
            similarities.append((case, combined_similarity))
        
        # 按相似度排序并返回前K个
        similarities.sort(key=lambda x: x[1], reverse=True)
        return similarities[:top_k]
    
    def calculate_text_similarity(self, text1: str, text2: str, method: str = 'combined') -> float:
        """
        计算两个文本的相似度
        
        Args:
            text1: 第一个文本
            text2: 第二个文本
            method: 相似度计算方法 ('cosine', 'jaccard', 'combined')
            
        Returns:
            相似度值 (0-1)
        """
        if method == 'cosine':
            return self.calculate_cosine_similarity(text1, text2)
        elif method == 'jaccard':
            return self.calculate_jaccard_similarity(text1, text2)
        else:  # combined
            cosine_sim = self.calculate_cosine_similarity(text1, text2)
            jaccard_sim = self.calculate_jaccard_similarity(text1, text2)
            return 0.7 * cosine_sim + 0.3 * jaccard_sim

# 创建全局实例
similarity_matcher = SimilarityMatcher()